package Logica;

import java.awt.Graphics;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import Celdas.Agua;
import Celdas.Arena;
import Celdas.Asfalto;
import Celdas.Fuego;
import Celdas.NoTransitable;
import Celdas.Transitable;
import Excepciones.BoundaryViolationException;
import Excepciones.InvalidPositionException;
import Grafica.Grafica;
import PremiosYColeccionables.Baliza;
import PremiosYColeccionables.Caja;
import PremiosYColeccionables.Coleccionable;
import PremiosYColeccionables.Combustible;
import PremiosYColeccionables.Cono;
import PremiosYColeccionables.Destructible;
import PremiosYColeccionables.Municion;
import PremiosYColeccionables.Pared;
import PremiosYColeccionables.Planta;
import PremiosYColeccionables.Premio;
import PremiosYColeccionables.Puntos;
import Robot.Civil;
import Robot.Militar;
import Robot.Robot;
import TDALista.DoubleLinkedList;

//
//
//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : Untitled
//  @ File Name : Juego.java
//  @ Date : 18/10/2013
//  @ Author : 
//
//

import TDALista.Position;








import java.util.StringTokenizer;

import javax.swing.JPanel;


public class Juego {

	
	protected  BufferedReader buffer;
	protected  FileReader fileReader;
	protected  DoubleLinkedList<Transitable> transitables;
	protected  DoubleLinkedList<NoTransitable>  noTransitables;
	protected  DoubleLinkedList<Proyectil> proyectiles;
	protected  String arena, asfalto, agua, fuego, planta, caja, pared, municion, combustible,puntos,civil,militar,cono, baliza;
	protected  String dirMapa;
	protected Robot robo;
	protected  Transitable inicio,fin;
	protected  int prox, robot;
	protected  double angulo = 0;
	protected  int ancho = 0, alto = 0;
	protected  int anchoMapa = 0, altoMapa = 0;
	protected  Mapa mapa;
	protected  String dirFin = "arena50.jpg";


	
	public Juego(String dirMapa, int robot) {
		this.robot = robot;
		System.out.println("Juego: Constructor:" + dirMapa );

		civil = "civil.png";
		militar = "tanque50.png";

		


		this.dirMapa = dirMapa;

		crearListasObjetos();
		proyectiles = new DoubleLinkedList<Proyectil>();
		if (robot == 1)
			robo = new Militar(militar, inicio, this);
		else
			robo = new Civil(civil,inicio);
	
	}
	


	private void crearListasObjetos(){
		System.out.println("En clase Juego: crearListasObjetos:" + dirMapa);
		
		// El Metodo asume que el archivo contiene caracteres validos ( 0,1,2,3,4,5,6,7 )
		/* 0 = Arena
		 * 1 = Asfalto
		 * 2 = Agua
		 * 3 = Fuego
		 * 4 = Inicio Arena
		 * 5 = Inicio Asfalto
		 * 6 = Fin Arena
		 * 7 = Fin Asfalto
		 */
		
		//http://chuwiki.chuidiang.org/index.php?title=Lectura_y_Escritura_de_Ficheros_en_Java
		//http://www.lawebdelprogramador.com/codigo/Java/2315-Leer_una_linea_de_un_archivo_y_separar_sus_palabras.html
		
		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(dirMapa);
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		buffer = new BufferedReader (new InputStreamReader(inputStream));
		
		
		noTransitables = new DoubleLinkedList<NoTransitable>();
		transitables = new DoubleLinkedList<Transitable>();
		
		String linea = "";
		StringTokenizer palabra = new StringTokenizer(linea);
		
		int lectura = 0;
		int y = 0,x = 0;
		
		Transitable nuevoT;
		NoTransitable nuevoNT;
		Destructible dest = null;
		Premio pre = null;
		Coleccionable col = null;
		String aux;
		int extra = 0;
		int premio = 0;
		int coma = 0;
		
		 try {
			while((linea = buffer.readLine()) != null){
				
				palabra = new StringTokenizer(linea);

				while (palabra.hasMoreTokens()) {

					nuevoT = null;
					nuevoNT = null;

					aux = (palabra.nextToken());
					lectura = 0;
					extra = 0;
					premio = 0;
					coma = 0;
					
					//System.out.println(aux.length());
					for (int i = 0; i < aux.length(); i++)
					{
						System.out.print(aux.charAt(i));
					}
					System.out.println();
					for (int i = 0; i < aux.length(); i++)
					{
						
						if (aux.charAt(i) == ',')
							coma++;
						if (coma == 0){
							lectura *= 10;
							lectura += aux.charAt(i) - 48;
							
						}else if (coma == 1 && aux.charAt(i) != ','){
							extra *= 10;
							extra += aux.charAt(i)  - 48;
							
						}else if (coma == 2 && aux.charAt(i) != ','){
							premio *= 10;
							premio += aux.charAt(i)  - 48;
							
						}
						
					}

					System.out.println("lectura " + lectura);
					System.out.println("Extra " + extra);
					System.out.println("Premio " + premio);
					
					if (lectura == 0 || lectura > 4 && lectura < 19){
						if ( extra == 1 || extra == 2){
							System.out.println("Coleccionable " + extra);
							
							col = generarColeccionable(extra);
						}else if (extra > 2){
							System.out.println("Destructible con premio " + extra +"," + premio );
							dest = generarDestructible(extra,premio);
						}
						if (premio > 0 && premio < 4){
							System.out.println("Premio " +  premio );
							pre = generarPremio(premio);
						}
					}
					
					if (lectura < 3 || lectura  > 4 && lectura < 12){
						String cadena =  retornarStringGraf(lectura);
						System.out.println("Creando Arena con: " + lectura + "  " + cadena + " en ("+x*ancho+","+ y*alto + ")");
						if (extra == 1 || extra == 2 )//&& lectura != 4 && lectura != 6)
							nuevoT = new Arena(x*ancho,y*alto,retornarStringGraf(lectura),col);
						else if (extra == 0 && premio > 0)// && lectura != 4 && lectura != 6)
							nuevoT = new Arena(x*ancho,y*alto,retornarStringGraf(lectura),pre);
						else if (extra > 2)//&& lectura != 4 && lectura != 6
							nuevoT = new Arena(x*ancho,y*alto,retornarStringGraf(lectura),dest);
						else 
							nuevoT = new Arena(x*ancho,y*alto,retornarStringGraf(lectura));
						
						if (lectura == 1){
							cadena =  retornarStringGraf(lectura);
							System.out.println("Creando Inicio Arena con: " + lectura + "  " + cadena + " en ("+x*ancho+","+ y*alto + ")");
							
							inicio = nuevoT;
						}else if (lectura == 2){
							//cadena =  retornarStringGraf(lectura);
							//System.out.println("Creando Fin Arena con: " + lectura + "  " + cadena + " en ("+x*ancho+","+ y*alto + ")");
							
							fin = nuevoT;
						}
					}else if (lectura == 3 || lectura == 4 || lectura > 11 && lectura < 19){// || lectura == 5 || lectura == 7){
						//String cadena =  retornarStringGraf(lectura);
						//System.out.println("Creando Asfalto con: " + lectura + "  " + cadena + " en ("+x*ancho+","+ y*alto + ")");
						if (extra == 1 || extra == 2 )
							nuevoT = new Asfalto(x*ancho,y*alto,retornarStringGraf(lectura),col);
						else if (extra == 0 && premio > 0)
							nuevoT = new Asfalto(x*ancho,y*alto,retornarStringGraf(lectura),pre);
						else if (extra > 2)
							
							nuevoT = new Asfalto(x*ancho,y*alto,retornarStringGraf(lectura),dest);
						else
							nuevoT = new Asfalto(x*ancho,y*alto,retornarStringGraf(lectura));
						
						if (lectura == 3){
							
							inicio = nuevoT;
						}else if (lectura == 4)
						{
							
							fin = nuevoT;
						}
					}else if (lectura > 18 && lectura < 28 ){
						nuevoNT = new Agua(x*ancho,y*alto,retornarStringGraf(lectura));
					}else if (lectura > 27 ){
						nuevoNT = new Fuego(x*ancho,y*alto,retornarStringGraf(lectura));
					}
					
					if (lectura < 19){
						transitables.addLast(nuevoT);
						ancho = nuevoT.getGrafica().getWidth();
						alto = nuevoT.getGrafica().getHeight();
						
					}else if (lectura > 18){
						noTransitables.addLast(nuevoNT);
						ancho = nuevoNT.getGrafica().getWidth();
						alto = nuevoNT.getGrafica().getHeight();
						
						
					}
					x++;
					//System.out.println("Incremento x, ahora es igual a " + x);
					
					if (y == 0)
						anchoMapa += ancho;
					
				}
				x = 0;
				y++;
				//System.out.println("Incremento y, ahora es igual a " + y);
				
				altoMapa += alto;
				
			}
			
				
			
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
		 		
		 	
}
	
private String retornarStringGraf(int cod){
		
		String salida="";
		switch (cod) {
		case 0:
			salida = "arena50.jpg";
			break;
		case 1:
			salida = "arenaI.jpg";
			break;
		case 2:
			salida = "arenaF.png";
			break;
		case 3:
			salida = "asfaltoI.jpg";
			break;
		case 4:
			salida = "asfaltoF.png";
			break;
		case 5:
			salida = "arenaAb-Ar.png";
			break;
		case 6:
			salida = "arenaAb-D.png";
			break;
		case 7:
			salida = "arenaAr-D.png";
			break;
		case 8:
			salida = "arenaI-Ab.png";
			break;
		case 9:
			salida = "arenaI-Ar.png";
			break;
		case 10:
			salida = "arenaI-D.png";
			break;
		case 11:
			salida = "arenaCruce.png";
			break;
		case 12:
			salida = "asfaltoAb-Ar.png";
			break;
		case 13:
			salida = "asfaltoAb-D.png";
			break;
		case 14:
			salida = "asfaltoAr-D.png";
			break;
		case 15:
			salida = "asfaltoI-Ab.png";
			break;
		case 16:
			salida = "asfaltoI-Ar.png";
			break;
		case 17:
			salida = "asfaltoI-D.png";
			break;
		case 18:
			salida = "asfaltoCruce.png";
			break;
		case 19:
			salida = "agua50.jpg";
			break;
		case 20:
			salida = "aguaAb.png";
			break;
		case 21:
			salida = "aguaAb-D.png";
			break;
		case 22:
			salida = "aguaD.png";
			break;
		case 23:
			salida = "aguaAr.png";
			break;
		case 24:
			salida = "aguaAr-D.png";
			break;
		case 25:
			salida = "aguaI.png";
			break;
		case 26:
			salida = "aguaI-Ar.png";
			break;
		case 27:
			salida = "aguaI-Ab.png";
			break;
		case 28:
			salida = "fuego50.jpg";
			break;
		case 29:
			salida = "fuegoAb.png";
			break;
		case 30:
			salida = "fuegoAb-D.png";
			break;
		case 31:
			salida = "fuegoD.png";
			break;
		case 32:
			salida = "fuegoAr.png";
			break;
		case 33:
			salida = "fuegoAr-D.png";
			break;
		case 34:
			salida = "fuegoI.png";
			break;
		case 35:
			salida = "fuegoI-Ar.png";
			break;
		case 36:
			salida = "fuegoI-Ab.png";
			break;
		case 37:
			salida = "combustible50.png";
			break;
		case 38:
			salida = "puntos.gif";
			break;
		case 39:
			salida = "municion50.png";
			break;
		case 40:
			salida = "baliza50.gif";
			break;
		case 41:
			salida = "cono50.png";
			break;
		case 42:
			salida = "concreto.png"; //Pared
			break;
		case 43:
			salida = "caja50.png";
			break;
		case 44:
			salida = "planta50.png";
			break;
		case 45:
			salida = "combustible.png";
			break;
		case 46:
			salida = "puntos.gif";
			break;
		case 47:
			salida = "municion.png";
			break;

		default:
			break;
		}
		
		return salida;
		
	}	

private Destructible generarDestructible (int codigo, int premio){
		
		Destructible nuevo = null;
	
		System.out.println("      Codigo " + codigo);
		if (codigo == 3){ 
			System.out.println("          pared");
			nuevo = new Pared (retornarStringGraf(42),generarPremio(premio));
		}else if (codigo == 4) {
			System.out.println("          caja");
			nuevo = new Caja (retornarStringGraf(43),generarPremio(premio));
		}else if (codigo == 5) {
			System.out.println("           planta");
			nuevo = new Planta (retornarStringGraf(44),generarPremio(premio));
		}
		
		return nuevo;
	}
	
	private Coleccionable generarColeccionable (int codigo){
		Coleccionable nuevo = null;


		System.out.println("      Codigo " + codigo);
		if (codigo == 1){
			System.out.println("       baliza");
			nuevo = new Baliza (retornarStringGraf(40));
		}else if (codigo == 2) {
			System.out.println("       cono");
			nuevo = new Cono (retornarStringGraf(41));
		}
		
		return nuevo;
	}
	
	private Premio generarPremio(int codigo){

		Premio nuevo = null;
		System.out.println("      Codigo " + codigo);
		if (codigo == 1){
			System.out.println("        combustible");
			nuevo = new Combustible (retornarStringGraf(37));
		}else if (codigo == 2) {
			System.out.println("           puntos");
			nuevo = new Puntos (retornarStringGraf(38));
		}else if (codigo == 3) {
			System.out.println("          municion");
			nuevo = new Municion (retornarStringGraf(39));
		}
		
		return nuevo;
		
	}
	
	public Robot getRobot(){
		return robo;
	}
	
	public DoubleLinkedList <NoTransitable> getNoTransitables(){
		return noTransitables;
	}
	
	public DoubleLinkedList <Transitable> getTransitables(){
		return transitables;
	}
	/*
	public void RetrocederRobot(){
		
	}
	*/
	public void desplazarRobot() {
		
		int x = robo.getCeldaActual().getX();
		int y = robo.getCeldaActual().getY();
		
		
		
		int orientacionRobot = robo.getOrientacion();
		/* 0 = Sur
		 * 1 = Este
		 * 2 = Norte
		 * 3 = Oeste
		*/
		if (orientacionRobot == 0){
			y += alto ;
			
		}else if (orientacionRobot == 1){
			x += ancho;
			
		}else if (orientacionRobot == 2){
			y -= alto;
		}else if (orientacionRobot == 3){
			x -= ancho;
		}
		
		System.out.println("Avanzar");
		Transitable proxima = getCeldaAdyacente(x, y);
		
		if (proxima != null  && !proxima.hayObjeto() && !proxima.hayColeccionable() ){
			
				robo.avanzarCelda(proxima);
			
		}
	}
	
	public Transitable getCeldaAdyacente(int x, int y){
		
		Position<Transitable> aux = transitables.first();
		
		try {
			
			while (aux.element().getY() != y && aux != transitables.last()){
				aux = transitables.next(aux);
				
			}
			while (aux.element().getX() != x && aux != transitables.last() && aux.element().getY() == y){
				aux = transitables.next(aux);
			}
		
		} catch (InvalidPositionException | BoundaryViolationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if (aux.element().getY() == y && aux.element().getX() == x){
			return aux.element();
		}
		
		return null;
	}


	/**
	 * prox es solo para control!
	 * @return
	 */
	public int getProx(){
		return robo.getOrientacion();
	}
	
	public void girarRobotDerecha() {
		//if (robo.getOrientacion() == 0 )
		//	robo.girarIzquierda();
		//else
		System.out.println("Derecha");
			robo.girarDerecha();

	}
	
	public void girarRobotIzquierda() {
		//if (robo.getOrientacion() == 0 )
		//	robo.girarDerecha();
		//else
		
		robo.girarIzquierda();
	}
	
	public int obtenerPosicionRobot() {
		return robo.getOrientacion();
	}
	
	public void pintar() {
		System.out.println("Juego:pintar");
		robo.desplegarPincel();
	}
	
	public void dejarDePintar() {
		robo.rePlegarPincel();
	}
	
	public void setColorPincel(int c) {
		robo.setColorPincel(c);
	}
	
	public Coleccionable recogerColeccionable() {
		
		Coleccionable col = null;
		if( robo.getBaul().Espacio < 15){
		int orientacionRobot = robo.getOrientacion();
		int x = robo.getCeldaActual().getX();
		int y = robo.getCeldaActual().getY();
		
		if (orientacionRobot == 0){
			y -=alto;
		}else if (orientacionRobot == 1){
			x -=ancho;
		}else if (orientacionRobot == 2){
			y +=alto;
		}else if (orientacionRobot == 3){
			x +=ancho;
		}
		
		Transitable adyacente = getCeldaAdyacente(x, y);
		
		if (adyacente != null){
			if (adyacente.hayColeccionable()){
				col = adyacente.getColeccionable();
				robo.recogerColeccionable(col);
				adyacente.eliminarColeccionable();
			}
		}
		}
		return col;
	}

	public void descartarColeccionable (){
		int orientacionRobot = robo.getOrientacion();
		int x = robo.getCeldaActual().getX();
		int y = robo.getCeldaActual().getY();
		
		if (orientacionRobot == 0){
			y -=alto;
		}else if (orientacionRobot == 1){
			x -=ancho;
		}else if (orientacionRobot == 2){
			y +=alto;
		}else if (orientacionRobot == 3){
			x +=ancho;
		}
		
		Transitable adyacente = getCeldaAdyacente(x, y);
		if (adyacente != null){
			if (!adyacente.hayColeccionable()){
				adyacente.setColeccionable(robo.descartarColeccionable());
			}
		}
	}
	
	//Este es un metodo de la clase juego, no corresponde con el metodo de la clase JPanel
	public void paint(Graphics g){
		
		robo.draw(g);
	}
	
	public boolean esFinal(){
		return (robo.getX() == fin.getX() &&  robo.getY() == fin.getY());
	}
	
	public void reset(){
		
			transitables = null;
			crearListasObjetos();
			if (robot == 1)
				robo = new Militar(militar, inicio, this);
			else
				robo = new Civil(civil,inicio);
			
		
	}
	
	public void accionEspecialRobot(){
		robo.accionEspecial();
	}
	
	public DoubleLinkedList<Proyectil> getProyectiles(){
		return proyectiles;
	}

	public int getAltoMapa(){
		return altoMapa;
	}
	
	public int getAnchoMapa(){
		return anchoMapa;
	}
	
	public int getPuntos(){
		return robo.getPuntos();
	}
	
	public int getCombustible(){
		return robo.getCombustible();
	}
	
	public int getAtributoEspecial(){
		return robo.getAtributoEspecial();
	}
	
	
	public Baul getBaul(){

		return robo.getBaul();
	}
	
	public boolean getEstadoPincel(){
		return robo.getEstadoPincel();
	}
	

	public void guardarPartida(String nombre)
	{
		try {
			FileOutputStream fos = new FileOutputStream(nombre);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(this.robo);
			
			oos.close();
		} catch (FileNotFoundException e) {e.printStackTrace();}
		  catch (IOException e) {e.printStackTrace();}
	}



	public void cargarPartida(String nombreArchivo) {
		
		Robot robotRecuperado;
		
		try {
			FileInputStream fis = new FileInputStream(nombreArchivo);
			ObjectInputStream ois = new ObjectInputStream(fis);
			robotRecuperado = (Robot) ois.readObject();
			
			this.robo = robotRecuperado;
		
			ois.close();
			
		} catch (Exception e) {e.printStackTrace();}
		
	}
	
	
	

}
